package cn.fx.framework.spring.w;

import cn.fx.framework.W;
import cn.fx.framework.redis.MyRedisCacheManager;
import cn.fx.framework.redis.MyRedisTemplate;
import cn.fx.framework.spring.SpringBeanUtils;
import cn.fx.framework.spring.web.DefaultWebApplicationHandler;
import cn.fx.framework.web.ApplicationHandler;
import org.springframework.beans.BeansException;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.lang.reflect.Constructor;
import java.util.Objects;

/**
 * 初始化W实例
 * 步骤: 1、检查SpringBoot启动类上有无@EnableW配置，存在，则使用其指定的ApplicationHandler
 * 2、如果没有@EnableW配置，查找properties文件中site.application.handler配置，存在，则使用其指定的ApplicationHandler
 * 3、如果以上都没有配置，则使用cn.fx.framework中的默认配置
 * 4、配置完成 WebApplicationHandler之后，使用该Handler配置Redis缓存
 * 4.1、配置Redis缓存管理
 *
 * @author ljh
 * @since 2018-11-11 21:15
 **/
public class WStartListener implements ApplicationRunner, ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        ApplicationHandler handler;

        //先在springBoot启动类上查找EnableW标签
        EnableW ew = SpringBeanUtils.getAnnotationAtSpringBootApplication(applicationContext, EnableW.class);
        Class<? extends ApplicationHandler> clazz;
        if (ew == null) {
            //从application.properties里查找
            String className = applicationContext.getEnvironment().getProperty(W.APPLICATION_HANDLER_CLASS_NAME);

            try {
                clazz = (Class<? extends ApplicationHandler>) Class.forName(className);
            } catch (Exception e) {
                //没有配置或配置出错，则使用默认的webApplicationHandler
                clazz = DefaultWebApplicationHandler.class;
            }
        } else {
            clazz = ew.handler();
        }

        //检查是否已经存在了ApplicationHandler对应的Bean，查找并赋值
        try {
            handler = applicationContext.getBean(clazz);
        } catch (Exception e) {
            handler = null;
        }
        if (Objects.isNull(handler)) {
            try {
                Constructor<?> constructor = clazz.getConstructor(ApplicationContext.class);
                handler = (ApplicationHandler) constructor.newInstance(applicationContext);
            } catch (Exception e) {
                e.printStackTrace();
                throw new Error("SpringBoot启动类上标记的EnableW所指定的handler类初始化时失败，异常：" + e.getMessage());
            }
        }

        //设置MyRedisCacheManager
        try {
            handler.setRedisCacheMananger(applicationContext.getBean(MyRedisCacheManager.class));
        } catch (BeansException be) {
            throw new Error("spring上下文中没有MyRedisCacheManager定义。");
        }
        //设置MyRedisTemplate
        try {
            handler.setMyRedisTemplate(applicationContext.getBean(MyRedisTemplate.class));
        } catch (BeansException be) {
            throw new Error("spring上下文中没有MyRedisTemplate定义。");
        }
        W.getInstance().initHandler(handler);
    }

}
